package org.theSeed.dataSource.pojo.prop;

import cn.hutool.core.util.ObjectUtil;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Getter;
import lombok.Setter;
import org.theSeed.base.exp.ServiceExp;
import org.theSeed.base.utils.DeepCopyUtil;
import org.theSeed.dataSource.contract.DataSourceProp;
import org.theSeed.dataSource.pojo.dto.RelDbConnectInfo;
import org.theSeed.dataSource.pojo.dto.SeedHikariDataSourcePool;

import javax.sql.DataSource;
import java.util.Map;

/**
 * Hikari数据源配置
 */
@Getter
@Setter
public class HikariProp implements DataSourceProp {
    /**
     * 连接池名称
     */
    private String poolName = "seedHikariPool";
    /**
     * 最大连接数
     */
    private Integer maximumPoolSize = 5;
    /**
     * 最小空闲连接
     */
    private Integer minimumIdle = 5;
    /**
     * 连接超时时间(毫秒)
     */
    private Integer connectionTimeout = 30000;
    /**
     * 空闲连接超时时间(毫秒)
     */
    private Integer idleTimeout = 600000;
    /**
     * 连接最大存活时间(毫秒)
     */
    private Integer maxLifetime = 1800000;




    //高级配置
    /**
     * 连接测试查询
     * SELECT 1
     */
    private String connectionTestQuery;
    /**
     * 连接泄漏检测（毫秒）
     * 60000
     */
    private Long leakDetectionThreshold = 60000l;
    /**
     * 连接初始化SQL
     * SET time_zone = '+8:00'
     */
    private String connectionInitSql;
    /**
     * 只读模式
     * false
     */
    private Boolean readOnly = false;
    /**
     * 隔离级别
     * TRANSACTION_READ_COMMITTED
     */
    private String transactionIsolation;
    /**
     * 连接验证
     * -1
     */
    private Long initializationFailTimeout = -1l;

    /**
     * 连接自定义属性
     */
    private Map<String,String> dataSourcePropertyMap;

    private HikariConfig config;

    /**
     * 创建数据源
     * @param prop
     * @return
     */
    @Override
    public synchronized DataSource createDataSource(Object prop){
        if (prop instanceof RelDbConnectInfo){
            RelDbConnectInfo relDbConnectInfo = (RelDbConnectInfo)prop;
            if (ObjectUtil.isNull(config)){
                config = new SeedHikariDataSourcePool();

                // 连接池优化配置
                config.setPoolName(getPoolName()); // 连接池名称
                config.setMaximumPoolSize(getMaximumPoolSize());      // 最大连接数
                config.setMinimumIdle(getMinimumIdle());           // 最小空闲连接
                config.setConnectionTimeout(getConnectionTimeout());  // 连接超时时间(毫秒)
                config.setIdleTimeout(getIdleTimeout());      // 空闲连接超时时间(毫秒)
                config.setMaxLifetime(getMaxLifetime());     // 连接最大存活时间(毫秒)

                //高级设置
                config.setConnectionTestQuery(getConnectionTestQuery());
                config.setLeakDetectionThreshold(getLeakDetectionThreshold());
                config.setConnectionInitSql(getConnectionInitSql());
                config.setReadOnly(getReadOnly());
                config.setTransactionIsolation(getTransactionIsolation());
                config.setInitializationFailTimeout(getInitializationFailTimeout());

                /**
                 * 自定义属性
                 */
                if (getDataSourcePropertyMap() != null){
                    getDataSourcePropertyMap().entrySet()
                            .stream()
                            .forEach(item->{
                                config.addDataSourceProperty(item.getKey(),item.getValue());
                            });
                }
            }

            HikariConfig hikariConfig = DeepCopyUtil.deepCopy(config);
            // 基本配置
            hikariConfig.setJdbcUrl(relDbConnectInfo.getJdbcUrl());
            hikariConfig.setUsername(relDbConnectInfo.getUsername());
            hikariConfig.setPassword(relDbConnectInfo.getPassword());
            hikariConfig.setDriverClassName(relDbConnectInfo.getDriverClassName());
            return new HikariDataSource(hikariConfig);
        }
        throw new ServiceExp("不支持配置初始化数据源");
    }
}
